// This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © Trendoscope Pty Ltd, Trendoscope®
//                                       ░▒             
//                                  ▒▒▒   ▒▒      
//                              ▒▒▒▒▒     ▒▒      
//                      ▒▒▒▒▒▒▒░     ▒     ▒▒          
//                  ▒▒▒▒▒▒           ▒     ▒▒          
//             ▓▒▒▒       ▒        ▒▒▒▒▒▒▒▒▒▒▒  
//   ▒▒▒▒▒▒▒▒▒▒▒ ▒        ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒         
//   ▒  ▒       ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░        
//   ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒▒▒▒▒▒▒▒         
//   ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒                       
//    ▒▒▒▒▒         ▒▒▒▒▒▒▒                            
//                 ▒▒▒▒▒▒▒▒▒                           
//                ▒▒▒▒▒ ▒▒▒▒▒                          
//               ░▒▒▒▒   ▒▒▒▒▓      ████████╗██████╗ ███████╗███╗   ██╗██████╗  ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗
//              ▓▒▒▒▒     ▒▒▒▒      ╚══██╔══╝██╔══██╗██╔════╝████╗  ██║██╔══██╗██╔═══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝
//              ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒        ██║   ██████╔╝█████╗  ██╔██╗ ██║██║  ██║██║   ██║███████╗██║     ██║   ██║██████╔╝█████╗ 
//             ▒▒▒▒▒       ▒▒▒▒▒       ██║   ██╔══██╗██╔══╝  ██║╚██╗██║██║  ██║██║   ██║╚════██║██║     ██║   ██║██╔═══╝ ██╔══╝  
//            ▒▒▒▒▒         ▒▒▒▒▒      ██║   ██║  ██║███████╗██║ ╚████║██████╔╝╚██████╔╝███████║╚██████╗╚██████╔╝██║     ███████╗
//             ▒▒             ▒                        
//@version=5
import Trendoscope/Drawing/1 as dr
import Trendoscope/Zigzag/7 as zg
import HeWhoMustNotBeNamed/utils/1 as ut
import Trendoscope/Waves/1 as w

indicator("Motive Wave Scanner [Trendoscope®]", "MW[Trendoscope®]", overlay = true, max_lines_count=500, max_labels_count=500, max_bars_back = 1000)
theme = input.string('Dark', title='Theme', options=['Light', 'Dark'], group='Generic Settings',
         tooltip='Chart theme settings. Line and label colors are generted based on the theme settings. If dark theme is selected, '+
         'lighter colors are used and if light theme is selected, darker colors are used.', display=display.none)

zigzagLength = input.int(5, step=5, minval=3, title='Length', group='Zigzag', tooltip='Zigzag length for level 0 zigzag', display=display.none)
depth = input.int(200, "Depth", step=25, maxval=500, group='Zigzag', tooltip='Max number of zigzag swings to consider for recursive calculation', display=display.none)

levelType = input.string('Minimum', 'Level', ['Minimum', 'Absolute'], group = 'Waves', inline='l', display=display.none)
level = input.int(1, "", group='Waves', minval = 1, inline='l', tooltip = 'Zigzag Level to consider for scanning waves', display=display.none)
limitSubwaves = input.bool(false, "Draw only first subwave", group='Waves', tooltip = 'If there are multiple subwave combinations, draw only the first so that chart will look cleaner', display=display.none)
repaint = input.bool(false, "Rapaint", group="Waves", inline='r', display=display.none, tooltip = 'If selected, waves are identified immediately, but the formations can repaint. If repaint is not selected, 
         then the waves are only presented after the confirmation. This means, there may be delay in printing the formation.
         Please note that, due to some internal pine issues, if repaint is selected, the indicator may throw some runtime error when running through the alerts')

useRealTimeBars = true

allowedTypes = array.from(w.WaveType.ContractingDiagonal, w.WaveType.ExpandingDiagonal, w.WaveType.ImpulseWave)
offset = useRealTimeBars? 0 : 1

indicators = matrix.new<float>()
indicatorNames = array.new<string>()

var themeColors = ut.getColors(theme)
var zg.Zigzag zigzag = zg.Zigzag.new(zigzagLength, depth, offset)
zigzag.calculate(array.from(high, low), indicators, indicatorNames)

var array<w.Wave> motiveWaves = array.new<w.Wave>()

method createWave(zg.Pivot pivot, color lineColor, array<w.Wave> waves, int limit = 10)=>
    dr.Line ln = pivot.point.createLine(pivot.subPivots.last().point, dr.LineProperties.new(color = lineColor))
    dr.LabelProperties lblProps = dr.LabelProperties.new(color = lineColor, textcolor = chart.bg_color, size = size.normal, style = math.sign(pivot.dir) > 0? label.style_label_lower_left : label.style_label_upper_left)
    dr.Label lbl = pivot.point.createLabel('Motive Wave', properties = lblProps)
    w.Wave wave = w.Wave.new(pivot, ln, lbl, array.new<w.Subwave>())
    if(repaint)
        for [index, existingWave] in waves
            if(ln.end.index == existingWave.wave.end.index)
                waves.remove(index).delete()
                break
        waves.unshift(wave)
        if(waves.size() > limit)
            waves.pop().delete()
    wave

if(zigzag.flags.newPivot and (repaint or not zigzag.flags.updateLastPivot))
    mlzigzag = zigzag
    rowNum = 0
    while(mlzigzag.zigzagPivots.size() >= 3)
        if(levelType == 'Minimum'? mlzigzag.level >= level : mlzigzag.level == level)
            pivot = repaint? mlzigzag.zigzagPivots.first() : mlzigzag.zigzagPivots.get(1)
            lastPivot = repaint? mlzigzag.zigzagPivots.get(1) : mlzigzag.zigzagPivots.get(2)
            if(not repaint or bar_index == pivot.point.index)
                motiveSubwaveIndices = pivot.scanMotiveWave(lastPivot, motiveWaves, allowedTypes)
                if(motiveSubwaveIndices.size()>0)
                    alert('New Motive wave detected')
                    if(barstate.islast and barstate.isrealtime)
                        log.info('New ImpuMotivelse wave detected')
                    labelColor = themeColors.shift()
                    themeColors.push(labelColor)

                    motiveWave = pivot.createWave(labelColor, motiveWaves).
                                         createSubWaves(motiveSubwaveIndices).
                                         draw(limitSubwaves)
            else
                break
        mlzigzag := mlzigzag.nextlevel()
        rowNum+=1
